package com.easyexcel.read;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;

import com.easyexcel.annotation.Excel;
import com.easyexcel.read.exception.LackCellAnnotation;
import com.easyexcel.util.ExcelUtil;
import com.easyexcel.util.MyStringUtils;

/**
 * 读取列表数据
 *
 * @param <T>
 * @author wangqh
 */
public class ReadListExcel<T> implements ReadExcel<T> {
    private String inFilePath;
    private int beginRow;

    @SuppressWarnings("unchecked")
    @Override
    public List<T> read(Map<String, Object> param, Class clazz) throws IOException, InstantiationException,
            IllegalAccessException {
        initParam(param, clazz);
        Workbook workbook = ExcelUtil.getWorkbookTypeByFile(inFilePath);
        if (workbook == null) {
            throw new FileNotFoundException("文件未找到！");
        }
        return readList(workbook, clazz);
    }

    @Override
    public List<T> read(Class clazz) throws IOException, InstantiationException, IllegalAccessException {
        return this.read(null, clazz);
    }

    private void initParam(Map<String, Object> param, Class clazz) {
        if (param != null) {
            if (param.get("inFilePath") != null) {
                inFilePath = param.get("inFilePath").toString();
            }
            if (param.get("beginRow") != null) {
                beginRow = Integer.parseInt(param.get("beginRow").toString());
            }
        } else {
            Excel excel = (Excel) clazz.getAnnotation(Excel.class);
            if (excel != null) {
                inFilePath = excel.inFilePath();
                beginRow = excel.beginRow();
            }
        }

    }

    @SuppressWarnings("unchecked")
    private List<T> readList(Workbook workbook, Class clazz) throws InstantiationException, IllegalAccessException {
        List<T> list = new ArrayList<T>();
        Excel excel = (Excel) clazz.getAnnotation(Excel.class);
        if (excel != null) {
            beginRow = excel.beginRow();
        }
        for (int sheetIndex = 0; sheetIndex < workbook.getNumberOfSheets(); sheetIndex++) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            for (int rowIndex = beginRow; rowIndex <= sheet.getLastRowNum(); rowIndex++) {
                T it = (T) clazz.newInstance();
                Row row = sheet.getRow(rowIndex);
                if (row == null) {
                    continue;
                }
                for (int columnIndex = 0; columnIndex < row.getLastCellNum(); columnIndex++) {
                    Cell cell = row.getCell(columnIndex);
                    String value = ExcelUtil.getCellStringValue(cell);
                    if (MyStringUtils.isDecimalPointOfManyZero(value)) {
                        value = value.split("\\.")[0];
                    }
                    for (Field field : clazz.getDeclaredFields()) {
                        com.easyexcel.annotation.Cell ca = field.getAnnotation(com.easyexcel.annotation.Cell.class);
                        if (ca == null) {
                            continue;
                        }
                        int cn = ExcelUtil.cellTNumByCa(ca);
                        if (columnIndex == (cn - 1)) {
                            field.setAccessible(true);
                            String type = field.getGenericType().toString();
                            if (type.equals("class java.lang.Integer") || type.equals("int")) {
                                field.set(it, Integer.parseInt(value));
                            } else if (type.equals("class java.lang.Double") || type.equals("double")) {
                                field.set(it, Double.parseDouble(value));
                            } else if (type.equals("class java.lang.Boolean") || type.equals("boolean")) {
                                field.set(it, Boolean.parseBoolean(value));
                            } else {
                                field.set(it, value);
                            }
                        }
                    }
                }
                list.add(it);
            }
        }
        return list;
    }

}
